#include "SettingsManager.h"

SettingsManager::SettingsManager(EnginePointer<ISerializer> serializer)
{
	this->serializer = serializer;
}

SettingsManager::~SettingsManager()
{
	for (map<char*, char*, SettingsManagerStringCmp>::iterator it = settingMap.begin(); it != settingMap.end(); it++)
	{
		free(it->first);
		free(it->second);
	}
}

char* SettingsManager::GetVariableAsString(char* name)
{
	return settingMap[name];
}

bool SettingsManager::GetVariableAsBool(char* name)
{
	return atoi(settingMap[name]) != 0;
}

signed char SettingsManager::GetVariableAsSChar(char* name)
{
	return (signed char)settingMap[name][0];
}

unsigned char SettingsManager::GetVariableAsUChar(char* name)
{
	return (unsigned char)settingMap[name][0];
}

signed short int SettingsManager::GetVariableAsSShort(char* name)
{
	return (signed short int)atoi(settingMap[name]);
}

unsigned short int SettingsManager::GetVariableAsUShort(char* name)
{
	return (unsigned short int)atoi(settingMap[name]);
}

signed long int SettingsManager::GetVariableAsSLong(char* name)
{
	return (signed long int)atol(settingMap[name]);
}

unsigned long int SettingsManager::GetVariableAsULong(char* name)
{
	return (unsigned long int)atol(settingMap[name]);
}

float SettingsManager::GetVariableAsFloat(char* name)
{
	return (float)atof(settingMap[name]);
}

double SettingsManager::GetVariableAsDouble(char* name)
{
	return atof(settingMap[name]);
}

long double SettingsManager::GetVariableAsLongDouble(char* name)
{
	_LDOUBLE value;
	_atoldbl(&value, settingMap[name]);
	return *((double*)value.ld);
}

signed long long SettingsManager::GetVariableAsSLongLong(char* name)
{
	return (signed long long)_atoi64(settingMap[name]);
}

unsigned long long SettingsManager::GetVariableAsULongLong(char* name)
{
	return (unsigned long long)_atoi64(settingMap[name]);
}

void SettingsManager::SetVariable(char* name, char* value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%s", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%s", value);
}

void SettingsManager::SetVariable(char* name, bool value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%i", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%i", value);
}

void SettingsManager::SetVariable(char* name, signed char value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%c", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%c", value);
}

void SettingsManager::SetVariable(char* name, unsigned char value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%c", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%c", value);
}

void SettingsManager::SetVariable(char* name, signed short int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%d", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%d", value);
}

void SettingsManager::SetVariable(char* name, unsigned short int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%u", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%u", value);
}

void SettingsManager::SetVariable(char* name, signed long int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%d", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%d", value);
}

void SettingsManager::SetVariable(char* name, unsigned long int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%u", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%u", value);
}

void SettingsManager::SetVariable(char* name, float value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%f", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%f", value);
}

void SettingsManager::SetVariable(char* name, double value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%f", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%f", value);
}

void SettingsManager::SetVariable(char* name, long double value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%f", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%f", value);
}

void SettingsManager::SetVariable(char* name, signed long long int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%f", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%f", value);
}

void SettingsManager::SetVariable(char* name, unsigned long long int value)
{
	if (settingMap.find(name) != settingMap.end())
	{
		free(settingMap[name]);
	}

	int nameLen = strlen(name);
	char* nameCopy = (char*)malloc((nameLen + 1) * sizeof(char));
	strcpy_s(nameCopy, nameLen + 1, name);
	int len = _scprintf("%i", value);
	settingMap[nameCopy] = (char*)malloc((len + 1) * sizeof(char));
	sprintf_s(settingMap[nameCopy], len + 1, "%i", value);
}

void SettingsManager::ReadSettings()
{
	for (map<char*, char*, SettingsManagerStringCmp>::iterator it = settingMap.begin(); it != settingMap.end(); it++)
	{
		free(it->first);
		free(it->second);
	}
	settingMap.clear();
	
	serializer->BeginDeserialization();

	if (strcmp("Settings", serializer->CurrentName()) == 0)
	{
		int index = 0;
		char* childName = serializer->ChildName(index);

		while (childName != NULL)
		{
			char* childValue = serializer->ChildValue(index);
			SetVariable(childName, childValue);

			childName = serializer->ChildName(++index);
		}
	}

	serializer->EndDeserialization();
}

void SettingsManager::WriteSettings()
{
	serializer->BeginSerialization();
	serializer->StartItem("Settings");

	for (map<char*, char*, SettingsManagerStringCmp>::iterator it = settingMap.begin(); it != settingMap.end(); it++)
	{
		serializer->SerializeProperty((*it).first, (*it).second);
	}

	serializer->EndItem("Settings");
	serializer->EndSerialization();
}
